{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "HhR5048dZ3e1"
      },
      "source": [
        "##### Copyright 2019 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "f0A2utIXbPc5"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "1qF0JETfbfIR"
      },
      "source": [
        "# Mandelbrot set"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "p8Z8Pb5nbtZ3"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs/blob/master/site/en/r1/tutorials/non-ml/mandelbrot.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Run in Google Colab</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs/blob/master/site/en/r1/tutorials/non-ml/mandelbrot.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />View source on GitHub</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "p8Z8Pb5nbtZ3"
      },
      "source": [
        "> Note: This is an archived TF1 notebook. These are configured\n",
        "to run in TF2's \n",
        "[compatbility mode](https://www.tensorflow.org/guide/migrate)\n",
        "but will run in TF1 as well. To use TF1 in Colab, use the\n",
        "[%tensorflow_version 1.x](https://colab.research.google.com/notebooks/tensorflow_version.ipynb)\n",
        "magic."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "lqPLlJWqcSFZ"
      },
      "source": [
        "Visualizing the [Mandelbrot set](https://en.wikipedia.org/wiki/Mandelbrot_set) doesn't have anything to do with machine learning, but it makes for a fun example of how one can use TensorFlow for general mathematics. This is actually a pretty naive implementation of the visualization, but it makes the point. (We may end up providing a more elaborate implementation down the line to produce more truly beautiful images.)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "80RrFh7EcnLT"
      },
      "source": [
        "## Basic setup\n",
        "\n",
        "You'll need a few imports to get started."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "xc-QSV_SdEG4"
      },
      "outputs": [],
      "source": [
        "# Import libraries for simulation\n",
        "import tensorflow.compat.v1 as tf\n",
        "\n",
        "import numpy as np\n",
        "\n",
        "# Imports for visualization\n",
        "import PIL.Image\n",
        "from io import BytesIO\n",
        "from IPython.display import clear_output, Image, display\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "mP5YEOuTieH0"
      },
      "source": [
        "Now you'll define a function to actually display the image once you have iteration counts."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "_q_HC5cGhX4h"
      },
      "outputs": [],
      "source": [
        "def DisplayFractal(a, fmt='jpeg'):\n",
        "  \"\"\"Display an array of iteration counts as a\n",
        "     colorful picture of a fractal.\"\"\"\n",
        "  a_cyclic = (6.28*a/20.0).reshape(list(a.shape)+[1])\n",
        "  img = np.concatenate([10+20*np.cos(a_cyclic),\n",
        "                        30+50*np.sin(a_cyclic),\n",
        "                        155-80*np.cos(a_cyclic)], 2)\n",
        "  img[a==a.max()] = 0\n",
        "  a = img\n",
        "  a = np.uint8(np.clip(a, 0, 255))\n",
        "  f = BytesIO()\n",
        "  PIL.Image.fromarray(a).save(f, fmt)\n",
        "  display(Image(data=f.getvalue()))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "xEptO88QikEM"
      },
      "source": [
        "# Session and variable initialization\n",
        "\n",
        "For playing around like this, an interactive session is often used, but a regular session would work as well."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "8_yDY6Uih7bD"
      },
      "outputs": [],
      "source": [
        "sess = tf.InteractiveSession()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "_NFwmNL5iqBd"
      },
      "source": [
        "It's handy that you can freely mix NumPy and TensorFlow."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "fHu_sT7chbg_"
      },
      "outputs": [],
      "source": [
        "# Use NumPy to create a 2D array of complex numbers\n",
        "\n",
        "Y, X = np.mgrid[-1.3:1.3:0.005, -2:1:0.005]\n",
        "Z = X+1j*Y"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "u7SsqtHqivVW"
      },
      "source": [
        "Now you define and initialize TensorFlow tensors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "UpGYdAWQhhCN"
      },
      "outputs": [],
      "source": [
        "xs = tf.constant(Z.astype(np.complex64))\n",
        "zs = tf.Variable(xs)\n",
        "ns = tf.Variable(tf.zeros_like(xs, tf.float32))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "gqvhBLXbi4al"
      },
      "source": [
        "TensorFlow requires that you explicitly initialize variables before using them."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "RmjN39LHhob2"
      },
      "outputs": [],
      "source": [
        "tf.global_variables_initializer().run()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ao_esnw4jAJp"
      },
      "source": [
        "# Defining and running the computation\n",
        "\n",
        "Now you specify more of the computation..."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ZMup0FHjiGEx"
      },
      "outputs": [],
      "source": [
        "# Compute the new values of z: z^2 + x\n",
        "zs_ = zs*zs + xs\n",
        "\n",
        "# Have we diverged with this new value?\n",
        "not_diverged = tf.abs(zs_) < 4\n",
        "\n",
        "# Operation to update the zs and the iteration count.\n",
        "#\n",
        "# Note: We keep computing zs after they diverge! This\n",
        "#       is very wasteful! There are better, if a little\n",
        "#       less simple, ways to do this.\n",
        "#\n",
        "step = tf.group(\n",
        "  zs.assign(zs_),\n",
        "  ns.assign_add(tf.cast(not_diverged, tf.float32))\n",
        "  )"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "9qqqbNu7jCrj"
      },
      "source": [
        "... and run it for a couple hundred steps"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "twC_FiUSiN8s"
      },
      "outputs": [],
      "source": [
        "for i in range(200): step.run()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vfoDAWtijLKd"
      },
      "source": [
        "Let's see what you've got."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "8qqfdbuOiV90"
      },
      "outputs": [],
      "source": [
        "DisplayFractal(ns.eval())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vB-3S5cFjVYQ"
      },
      "source": [
        "Not bad!"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "name": "mandelbrot.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
